package com.example.owl.viewmodel

//import android.util.Base64
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.owl.model.Message
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.nio.charset.StandardCharsets
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.util.Base64

class ChatViewModel : ViewModel() {

    private val client = HttpClient()

    private val _messages = MutableStateFlow<List<Message>>(emptyList())
    val messages: StateFlow<List<Message>> get() = _messages

    @RequiresApi(Build.VERSION_CODES.O)
    fun sendMessage(userMessage: String) {
        _messages.value = _messages.value + Message(userMessage, true)
        viewModelScope.launch {
            val response = getResponseFromApi(userMessage)
            _messages.value = _messages.value + Message(response, false)
        }
    }

    fun clearMessages() {
        _messages.value = emptyList()
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private suspend fun getResponseFromApi(message: String): String {
        val appId = "3038829806"
        val appKey = "TBuEChVfAsxpKDsR"
        val method = "POST"
        val uri = "/vivogpt/completions"
        val domain = "api-ai.vivo.com.cn"

        val requestId = UUID.randomUUID().toString()
        val sessionId = UUID.randomUUID().toString()

        val query = mapOf("requestId" to requestId)
        val queryStr = mapToQueryString(query)
        val headers = genSignHeaders(appId, appKey, method, uri, queryStr)

        val data = """
        {
            "prompt": "$message",
            "model": "vivo-BlueLM-TB",
            "sessionId": "$sessionId"
            
        }
        """.trimIndent()

        val url = "https://$domain$uri?$queryStr"

        println("Request URL: $url")
        println("Request Body: $data")
        println("Request Headers: $headers")
        println("Request Query Params: $queryStr")

        return try {
            val response: HttpResponse = client.post(url) {
                contentType(ContentType.Application.Json)
                body = data
                headers.forEach { (key, value) ->
                    header(key, value)
                }
            }

            println("Response Status: ${response.status}")

            if (response.status == HttpStatusCode.OK) {
                val responseBody = response.readText()
                val resObj = parseResponse(responseBody)
                println("Response Body: ${responseBody}")
                if (resObj.data != null) {
                    resObj.data.content
                } else {
                    resObj.msg
                }
            } else {
                "Error: ${response.status}"
            }
        } catch (e: Exception) {
            e.printStackTrace()
            "网络错误: ${e.message}"
        }
    }

    private fun mapToQueryString(map: Map<String, String>): String {
        return map.entries.joinToString("&") { "${it.key}=${it.value}" }
    }
    private fun generateNonce(length: Int = 8): String {
        val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
        return (1..length)
            .map { allowedChars.random() }
            .joinToString("")
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun genSignHeaders(appId: String, appKey: String, method: String, uri: String, queryStr: String): Map<String, String> {
        val methodUpper = method.uppercase(Locale.getDefault())
        val timestamp = (System.currentTimeMillis() / 1000).toString()
        val nonce = generateNonce()
        val signedHeadersString = "x-ai-gateway-app-id:$appId\nx-ai-gateway-timestamp:$timestamp\nx-ai-gateway-nonce:$nonce"
        val signingString = "$methodUpper\n$uri\n$queryStr\n$appId\n$timestamp\n$signedHeadersString"

        println("Signing String: $signingString")

        val signature = generateSignature(appKey, signingString)

        println("Generated Signature: $signature")

        return mapOf(
            "Content-Type" to "application/json",
            "X-AI-GATEWAY-APP-ID" to appId,
            "X-AI-GATEWAY-TIMESTAMP" to timestamp,
            "X-AI-GATEWAY-NONCE" to nonce,
            "X-AI-GATEWAY-SIGNED-HEADERS" to "x-ai-gateway-app-id;x-ai-gateway-timestamp;x-ai-gateway-nonce",
            "X-AI-GATEWAY-SIGNATURE" to signature
        )
    }

//    private fun generateSignature(appKey: String, signingString: String): String {
//        val secretKeySpec = SecretKeySpec(appKey.toByteArray(StandardCharsets.UTF_8), "HmacSHA256")
//        val mac = Mac.getInstance("HmacSHA256")
//        mac.init(secretKeySpec)
//        val rawHmac = mac.doFinal(signingString.toByteArray(StandardCharsets.UTF_8))
//        val hexHmac = rawHmac.joinToString("") { "%02x".format(it) }
//        return Base64.encodeToString(hexHmac.toByteArray(StandardCharsets.UTF_8), Base64.NO_WRAP)
//    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun generateSignature(appKey: String, signingString: String): String {
        return try {
            val mac = Mac.getInstance("HmacSHA256")
            val secret = SecretKeySpec(appKey.toByteArray(StandardCharsets.UTF_8), mac.algorithm)
            mac.init(secret)
            Base64.getEncoder().encodeToString(mac.doFinal(signingString.toByteArray(StandardCharsets.UTF_8)))
        } catch (err: Exception) {
            // logger.error("create sign exception", err)
            ""
        }
    }

    private fun parseResponse(responseBody: String): ChatResponse {
        var codeString = responseBody.substringAfter("\"code\":").substringBefore(",").trim()
        if (codeString.endsWith("}")) {
            codeString = codeString.substring(0, codeString.length - 1).trim()
        }
        val code = codeString.toInt()
        val message = responseBody.substringAfter("\"msg\":\"").substringBefore("\"").trim()
        val content = responseBody.substringAfter("\"content\":\"").substringBefore("\"").trim()
        return ChatResponse(code, message, ChatResponseData(content))
    }

}

data class ChatResponse(val code: Int, val msg: String, val data: ChatResponseData?)
data class ChatResponseData(val content: String)
